package com.shiikong_memory.yez.Arknights;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.shiikong_memory.yez.MySQLAPI.DaoImpl.SklandServer;
import com.shiikong_memory.yez.Tool.HMACSHA256;
import org.brotli.dec.BrotliInputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;

@Component
public class SklandAPI {

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    SklandServer sklandServer;

    /**
     * 密码登录鹰角通行证
     * @param user 用户名
     * @param password 密码
     * @return Json消息
     */
    public JSONObject getToken(String user, String password){
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("User-Agent", "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0");
            httpHeaders.add("Accept-Encoding", "gzip");
            httpHeaders.add("Connection", "close");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("phone", user);
            jsonObject.put("password", password);
            HttpEntity<JSON> fromEntity = new HttpEntity(jsonObject, httpHeaders);
            ResponseEntity<JSONObject> jsonObjectResponseEntity = restTemplate.postForEntity("https://as.hypergryph.com/user/auth/v1/token_by_phone_password", fromEntity, JSONObject.class);
            if (!jsonObjectResponseEntity.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(200))) {
                return null;
            }
            return jsonObjectResponseEntity.getBody();
        } catch (HttpClientErrorException e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    /**
     * 发送登录验证码
     * @param phone 手机号
     * @return Json消息
     */
    public JSONObject getPhoneCode(String phone){
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("User-Agent", "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0");
            httpHeaders.add("Accept-Encoding", "gzip");
            httpHeaders.add("Connection", "close");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("phone", phone);
            jsonObject.put("type", 2);
            HttpEntity<JSON> fromEntity = new HttpEntity(jsonObject, httpHeaders);
            ResponseEntity<JSONObject> jsonObjectResponseEntity = restTemplate.postForEntity("https://as.hypergryph.com/general/v1/send_phone_code", fromEntity, JSONObject.class);
            if (!jsonObjectResponseEntity.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(200))) {
                return null;
            }
            return jsonObjectResponseEntity.getBody();
        } catch (HttpClientErrorException e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    /**
     * 手机验证码登录鹰角通行证
     * @param phone 手机号
     * @param code 验证码
     * @return Json消息
     */
    public JSONObject getToken_phone(String phone, String code){
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("User-Agent", "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0");
            httpHeaders.add("Accept-Encoding", "gzip");
            httpHeaders.add("Connection", "close");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("phone", phone);
            jsonObject.put("code", code);
            HttpEntity<JSON> fromEntity = new HttpEntity(jsonObject, httpHeaders);
            ResponseEntity<JSONObject> jsonObjectResponseEntity = restTemplate.postForEntity("https://as.hypergryph.com/user/auth/v2/token_by_phone_code", fromEntity, JSONObject.class);
            if (!jsonObjectResponseEntity.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(200))) {
                return null;
            }
            return jsonObjectResponseEntity.getBody();
        } catch (HttpClientErrorException e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    /***
     * 验证token是否存活
     * @param token 鹰角通行证
     * @return 是否存活
     */
    public boolean verifyToken(String token){
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("User-Agent", "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0");
            httpHeaders.add("Accept-Encoding", "gzip");
            httpHeaders.add("Connection", "close");
            HttpEntity<?> fromEntity = new HttpEntity<>(httpHeaders);
            ResponseEntity<JSONObject> jsonObjectResponseEntity = restTemplate.exchange("https://as.hypergryph.com/user/info/v1/basic?token=" + token, HttpMethod.GET, fromEntity, JSONObject.class);
            if (!jsonObjectResponseEntity.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(200))) {
                return false;
            }
            return jsonObjectResponseEntity.getBody().getInteger("status") == 0;
        } catch (HttpClientErrorException e) {
            System.err.println(e.getMessage());
            return false;
        }
    }

    /**
     * 获取Code码
     * @param token 鹰角通行证
     * @return Code码
     */
    public String getCode(String token){
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("User-Agent", "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0");
            httpHeaders.add("Accept-Encoding", "gzip");
            httpHeaders.add("Connection", "close");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("appCode", "4ca99fa6b56cc2ba");
            jsonObject.put("token", token);
            jsonObject.put("type", 0);
            HttpEntity<JSON> fromEntity = new HttpEntity(jsonObject, httpHeaders);
            ResponseEntity<JSONObject> jsonObjectResponseEntity = restTemplate.exchange("https://as.hypergryph.com/user/oauth2/v2/grant", HttpMethod.POST, fromEntity, JSONObject.class);
            if (!jsonObjectResponseEntity.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(200))) {
                return null;
            }
            return jsonObjectResponseEntity.getBody().getJSONObject("data").getString("code");
        } catch (HttpClientErrorException e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    /**
     * 获取Cred码
     * @param code Code码
     * @return JSON数据
     */
    public JSONObject getCred(String code){
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("User-Agent", "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0");
            httpHeaders.add("Accept-Encoding", "gzip");
            httpHeaders.add("Connection", "close");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", code);
            jsonObject.put("kind", 1);
            HttpEntity<JSON> fromEntity = new HttpEntity(jsonObject, httpHeaders);
            ResponseEntity<JSONObject> jsonObjectResponseEntity = restTemplate.postForEntity("https://zonai.skland.com/api/v1/user/auth/generate_cred_by_code", fromEntity, JSONObject.class);
            if (!jsonObjectResponseEntity.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(200))) {
                return null;
            }
            return jsonObjectResponseEntity.getBody().getJSONObject("data");
        } catch (RestClientException e) {
            System.err.println(e.getMessage());
            return null;
        }
    }

    /**
     * 获取鹰角账号角色列表
     * @param cred Cred码
     * @param token 鹰角通行证
     * @return JSON数据
     */
    //获取账号角色列表
    public JSONObject get_binding_list(String cred,String token){
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("User-Agent", "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0");
            httpHeaders.add("Accept-Encoding", "gzip");
            httpHeaders.add("Connection", "close");
            try {
                URL url = new URL("https://zonai.skland.com/api/v1/game/player/binding");
                generate_signature(cred, token, "/api/v1/game/player/binding", url.getQuery(), httpHeaders);
            } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException |
                     MalformedURLException e) {
                throw new RuntimeException(e);
            }
            HttpEntity<?> formEntity = new HttpEntity<>(httpHeaders);
            ResponseEntity<JSONObject> jsonObjectResponseEntity = restTemplate.exchange("https://zonai.skland.com/api/v1/game/player/binding", HttpMethod.GET, formEntity, JSONObject.class);
            if (!jsonObjectResponseEntity.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(200))) {
                return null;
            }
            return jsonObjectResponseEntity.getBody();
        } catch (RuntimeException e) {
            System.err.println(e.getMessage());
            return null;
        }

    }

    /**
     * 森空岛签到
     * @param cred Cred码
     * @param token 鹰角通行证
     * @param uid 角色uuid
     * @return 是否签到成功
     */
    public boolean sign_in(String cred,String token, String uid){
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("User-Agent", "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0");
            httpHeaders.add("Accept-Encoding", "gzip");
            httpHeaders.add("Connection", "close");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("uid", uid);
            jsonObject.put("gameId", 1);
            try {
                generate_signature(cred, token, "/api/v1/game/attendance", jsonObject.toString(), httpHeaders);
            } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException e) {
                throw new RuntimeException(e);
            }
            HttpEntity<JSONObject> formEntity = new HttpEntity<JSONObject>(jsonObject,httpHeaders);
            ResponseEntity<JSONObject> jsonObjectResponseEntity = restTemplate.exchange("https://zonai.skland.com/api/v1/game/attendance", HttpMethod.POST, formEntity, JSONObject.class);
            if (!jsonObjectResponseEntity.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(200))) {
                return false;
            }
            if (jsonObjectResponseEntity.getBody().getInteger("code") !=0){
                return false;
            }
            return true;
        } catch (RuntimeException e) {
            System.err.println(e.getMessage());
            return false;
        }
    }

    /**
     * 获取明日方舟游戏数据
     * @param cred Cred码
     * @param token 鹰角通行证
     * @param uuid 明日方舟角色uuid
     * @return
     */
    public JSONObject getArknightsData(String cred,String token,String uuid){
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("User-Agent", "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0");
        httpHeaders.add("Accept-Encoding", "gzip");
        httpHeaders.add("Connection", "close");
        try {
            generate_signature(cred,token, "/api/v1/game/player/info", "uid="+uuid, httpHeaders);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException e) {
            throw new RuntimeException(e);
        }
        HttpEntity<?> formEntity = new HttpEntity<>(httpHeaders);
        ResponseEntity<byte[]> exchange = restTemplate.exchange("https://zonai.skland.com/api/v1/game/player/info?uid=" + uuid, HttpMethod.GET, formEntity, byte[].class);
        try {
            byte[] data = unGZip(new ByteArrayInputStream(exchange.getBody()));
            return JSONObject.parseObject(new String(data, StandardCharsets.UTF_8));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取明日方舟官服抽卡数据
     * @param token 鹰角通行证
     * @param i 页数
     * @return JSON数据
     */
    public JSONObject getLotteryData(String token, Integer i){
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("User-Agent", "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0");
        httpHeaders.add("Accept-Encoding", "gzip");
        httpHeaders.add("Connection", "close");
        List<MediaType> mediaTypeList = new ArrayList<>();
        mediaTypeList.add(MediaType.APPLICATION_JSON);
        httpHeaders.setAccept(mediaTypeList);
        HttpEntity<JSONObject> formEntity = new HttpEntity<JSONObject>(httpHeaders);
        ResponseEntity<byte[]> exchange = restTemplate.exchange("https://ak.hypergryph.com/user/api/inquiry/gacha?page=%d&token=%s&channelId=1".formatted(i, token), HttpMethod.GET, formEntity, byte[].class);
        String dataString;
        if (exchange.getHeaders().containsKey("Content-Encoding")){
            if (exchange.getHeaders().get("Content-Encoding").get(0).equals("gzip")){
                try {
                    byte[] data = unGZip(new ByteArrayInputStream(exchange.getBody()));
                    dataString = new String(data, StandardCharsets.UTF_8);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }else {
                dataString = new String(exchange.getBody(), StandardCharsets.UTF_8);
            }
        }else {
            dataString = new String(exchange.getBody(), StandardCharsets.UTF_8);
        }
        return JSONObject.parseObject(dataString);
    }

    /**
     * 验证cred是否存活
     * @param token 鹰角通行证
     * @param cred Cred码
     * @return JSON数据
     */
    public JSONObject verifyCred(String token,String cred){
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("User-Agent", "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0");
        httpHeaders.add("Accept-Encoding", "gzip");
        httpHeaders.add("Connection", "close");
        try {
            generate_signature(cred,token, "/api/v1/user/check", new URL("https://zonai.skland.com/api/v1/game/player/binding").getQuery(), httpHeaders);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException | MalformedURLException e) {
            throw new RuntimeException(e);
        }
        HttpEntity<?> formEntity = new HttpEntity<>(httpHeaders);
        return restTemplate.exchange("https://zonai.skland.com/api/v1/user/check", HttpMethod.GET,formEntity, JSONObject.class).getBody();
    }

    /**
     * 加签验证
     * @param cred Cred码
     * @param token 鹰角通行证
     * @param path 请求地址
     * @param body_or_query 请求参数
     * @param httpHeaders 需加密的请求头
     */
    public void generate_signature(String cred, String token, String path, String body_or_query, HttpHeaders httpHeaders) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
        String t = String.valueOf(Long.valueOf(String.valueOf(System.currentTimeMillis()).substring(0,10)));
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("platform", "1");
        jsonObject.put("timestamp", t);
        jsonObject.put("dId", "de9759a5afaa634f");
        jsonObject.put("vName", "1.15.0");
        if (body_or_query == null) body_or_query = "";
        String s = path + body_or_query + t + jsonObject.toString();
        //hmac-sha256加密
        String hash = HMACSHA256.sha256_HMAC(s, token);
        //md5加密
        String md5Password = DigestUtils.md5DigestAsHex(hash.getBytes());

        httpHeaders.add("platform", "1");
        httpHeaders.add("timestamp", t);
        httpHeaders.add("dId", "de9759a5afaa634f");
        httpHeaders.add("vName", "1.15.0");
        httpHeaders.add("sign", md5Password);

        httpHeaders.add("cred", cred);
    }

    /**
     * Gzip解压缩
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static byte[] unGZip(InputStream inputStream) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try (GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream)) {
            byte[] buf = new byte[4096];
            int len = -1;
            while ((len = gzipInputStream.read(buf, 0, buf.length)) != -1) {
                byteArrayOutputStream.write(buf, 0, len);
            }
            return byteArrayOutputStream.toByteArray();
        } finally {
            byteArrayOutputStream.close();
        }
    }

    /**
     * Brotli解压缩
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static byte[] unBrotli(InputStream inputStream) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try (BrotliInputStream brotliInputStream = new BrotliInputStream(inputStream)) {
            byte[] buf = new byte[4096];
            int len = -1;
            while ((len = brotliInputStream.read(buf, 0, buf.length)) != -1) {
                byteArrayOutputStream.write(buf, 0, len);
            }
            return byteArrayOutputStream.toByteArray();
        } finally {
            byteArrayOutputStream.close();
        }
    }
}
